<script setup lang="ts">
import { ref } from 'vue'
import {
  NCollapse,
  NCollapseItem,
  NSplit,
  NScrollbar,
  NIcon,
  NButton,
  NSpace,
  NModal,
  NButtonGroup
} from 'naive-ui'
import {
  AppsList20Regular,
  AppFolder20Regular,
  Add20Regular,
  Search20Regular,
  PlayCircle20Regular,
  PlayCircle20Filled,
  DocumentChevronDouble24Regular,
  DocumentChevronDouble24Filled,
  Save20Regular,
  Save20Filled
} from '@vicons/fluent'
import Attribute from '@/components/attribute.vue'
import Nodes from '@/components/nodes.vue'
import NodeEditor from '@/components/node-editor.vue'
import VScript from '@/components/vscript/index.vue'
import Console from '@/components/console.vue'
import ScriptService from '@/services/script.service'

const scriptService = new ScriptService()
const vscriptRef = ref<InstanceType<typeof VScript>>()
const editorRef = ref<InstanceType<typeof NodeEditor>>()
const nodesRef = ref<InstanceType<typeof Nodes>>()
const expandeds = ref<string[]>(['attributes', 'nodes'])
const showEditor = ref(false)
const maxWorkspaceSize = ref(window.innerHeight - 36 + 'px')
const workspaceSize = ref(window.innerHeight - 36 + 'px')
const currentFile = ref<string>()

function onSearch () {
  if (!expandeds.value.includes('nodes')) {
    expandeds.value.push('nodes')
  }
  setTimeout(() => {
    nodesRef.value?.search()
  }, 45)
}
function onNodeCancel () {
  showEditor.value = false
}
function onNodeSave () {
  const json = editorRef.value?.json()
  nodesRef.value?.add(json)
  showEditor.value = false
  editorRef.value?.reset()
}
async function onRun () {
  vscriptRef.value?.run()
}
function onConsoleShow () {
  const size = +workspaceSize.value.slice(0, -2)
  if (size > window.innerHeight - 36 - 120) {
    workspaceSize.value = window.innerHeight - 36 - 120 + 'px'
  }
}
function onSave () {
  const data = vscriptRef.value?.json()
  if (!data) {
    return
  }
  scriptService.save(JSON.stringify(data), currentFile.value)
}
async function onOpen () {
  const { path, data } = await scriptService.open()
  currentFile.value = path
  vscriptRef.value?.reset(data.nodes, data.edges)
}

window.addEventListener('resize', () => {
  maxWorkspaceSize.value = window.innerHeight - 36 + 'px'
})
</script>
<template>
  <div class="home">
    <n-split direction="horizontal" default-size="280px" max="320px" min="220px" :resize-trigger-size="3">
      <template #1>
        <n-scrollbar>
          <n-collapse v-model:expanded-names="expandeds">
            <n-collapse-item title="属性" name="attributes">
              <template #arrow>
                <n-icon>
                  <AppsList20Regular />
                </n-icon>
              </template>
              <n-scrollbar>
                <Attribute />
              </n-scrollbar>
            </n-collapse-item>
            <n-collapse-item class="no-content-padding" title="节点" name="nodes">
              <template #arrow>
                <n-icon>
                  <AppFolder20Regular />
                </n-icon>
              </template>
              <template #header-extra>
                <n-space size="small" align="center" :wrap-item="false">
                  <n-button text @click.stop="onSearch">
                    <n-icon size="20">
                      <Search20Regular />
                    </n-icon>
                  </n-button>
                  <n-button text @click.stop="showEditor = true">
                    <n-icon size="20">
                      <Add20Regular />
                    </n-icon>
                  </n-button>
                </n-space>
              </template>
              <Nodes ref="nodesRef" />
            </n-collapse-item>
          </n-collapse>
        </n-scrollbar>
      </template>
      <template #2>
        <n-split direction="vertical" :resize-trigger-size="3" v-model:size="workspaceSize" :max="maxWorkspaceSize" min="140px">
          <template #1>
            <VScript ref="vscriptRef" />
          </template>
          <template #2>
            <Console @show="onConsoleShow" />
          </template>
        </n-split>
      </template>
    </n-split>
    <n-button-group>
      <n-button type="primary" text class="btn run-button" @click.stop.prevent="onOpen">
        <n-icon size="28"><DocumentChevronDouble24Regular /></n-icon>
        <n-icon size="28"><DocumentChevronDouble24Filled /></n-icon>
      </n-button>
      <n-button type="primary" text class="btn run-button" @click.stop.prevent="onSave">
        <n-icon size="30"><Save20Regular /></n-icon>
        <n-icon size="30"><Save20Filled /></n-icon>
      </n-button>
      <n-button type="primary" text class="btn run-button" @click.stop.prevent="onRun">
        <n-icon size="30"><PlayCircle20Regular /></n-icon>
        <n-icon size="30"><PlayCircle20Filled /></n-icon>
      </n-button>
    </n-button-group>
    <n-modal class="node-editor-modal" v-model:show="showEditor" preset="card" :close-on-esc="false" title="新增节点"
      :mask-closable="false" :closable="false" :segmented="{
      content: 'soft',
      footer: 'soft'
    }">
      <NodeEditor ref="editorRef" />
      <template #footer>
        <n-button text type="warning" @click="onNodeCancel">取消</n-button>
        <n-button type="primary" @click="onNodeSave">保存</n-button>
      </template>
    </n-modal>
  </div>
</template>
<style scoped lang="less">
.home {
  .n-split {
    display: flex;
  }

  :deep(.n-split-pane-1) {
    background-color: #FFFFFF05;
  }

  :deep(.n-split__resize-trigger-wrapper) {
    opacity: 0.5;
  }

  .n-collapse {
    :deep(.n-collapse-item) {
      margin: 0 !important;

      .n-collapse-item__header {
        background-color: #FFFFFF08;
        padding: 8px !important;

        &.n-collapse-item__header--active {
          border-bottom: 1px solid var(--n-divider-color);
        }

        .n-collapse-item-arrow {
          transform: rotate(0) !important;
          margin-right: 5px;
        }
      }

      .n-collapse-item__content-inner {
        padding-top: 0 !important;

        .n-scrollbar-content {
          padding: 12px;
        }
      }
    }
  }
  :deep(.n-split-pane-1 .no-content-padding .n-scrollbar-content) {
    padding: 0 !important;
  }
  .n-button-group {
    position: fixed;
    top: 15px;
    right: 15px;
    z-index: 100;
    .btn {
      width: 30px;
      height: 30px;
      .n-icon {
        position: fixed;
        margin-left: -15px;
        transition: opacity 0.275s;
        &:last-of-type {
          opacity: 0;
        }
      }
      &:hover {
        .n-icon:last-of-type {
          opacity: 1;
        }
        .n-icon:first-of-type {
          opacity: 0;
        }
      }
      &:first-of-type {
        .n-icon :deep(g) {
          transform: translateX(1px);
        }
      }
    }
  }
}
</style>
<style lang="less">
.node-editor-modal {
  width: 100vw;
  height: 100vh;
  --n-padding-top: 12px !important;
  --n-padding-left: 12px !important;
  --n-padding-bottom: 12px !important;
  .n-card__content {
    margin: 0 !important;
    padding: 0 !important;
  }
  .n-card__footer {
    display: flex;
    justify-content: flex-end;
    margin: 0 !important;
    padding: var(--n-padding-bottom) var(--n-padding-left) !important;
    button {
      margin-left: 12px;
    }
  }
}
</style>
